package org.despair2D.utils.core 
{
	import org.despair2D.core.ListenerProp;
	import org.despair2D.debug.Logger;
	import org.despair2D.utils.ITimer;
	
	import org.despair2D.core.ns_despair;
	use namespace ns_despair;
	
	
final public class TimerProp implements ITimer
{
	
	public function TimerProp() 
	{
		timerId = ++m_count;
	}
	
	
	
	internal static const t_joiningFlag:uint  =  0x01;  // 待加入(运行中不可加入，下一帧加入)
	
	internal static const t_runningFlag:uint  =  0x02;  // 运行列表中
	
	internal static const t_gcFlag:uint       =  0x10;  // 已回收
	
	internal static const t_gcAutoFlag:uint   =  0x20;  // 自动回收
	
	
	
	/**
	 * 是否进行中
	 */
	final public function get running() : Boolean
	{
		return Boolean(m_flags & 0x0F);
	}
	
	
	/**
	 * 定时器名字
	 */
	final public function get timerName() : String
	{
		return m_timerName;
	}
	
	
	/**
	 * 延迟间隔
	 * 
	 * @see      支持动态改变延迟间隔，最小锁定0.3秒
	 */
	final public function get delay() : Number
	{
		return m_delay * 0.001;
	}
	
	final public function set delay( v:Number ) : void
	{
		m_delay = ( v > 0.03 ) ? v * 1000.0 : 30;
		m_goalTime = this.m_manager.m_systemTime + m_delay;
	}
	
	
	/**
	 * 已触发次数
	 */
	final public function get currentCount() : int
	{
		return m_currentCount;
	}
	
	
	/**
	 * 总次数
	 */
	final public function get repeatCount() : int
	{
		return m_repeatCount;
	}
	
	
	

	/**
	 * 开始
	 */
	final public function start() : void
	{
		if (m_flags & t_gcFlag)
		{
			Logger.reportError(this, 'start', '定时器已回收.');
		}
		
		if (m_flags & 0x0F)
		{
			return;
		}
		
		// 检测是否自动运行
		this.m_manager.checkAutoStart();

		if (this.m_manager.duringAdvance)
		{
			this.m_manager.m_joiningList[this.m_manager.m_joiningLength++] = this;
			m_flags |= t_joiningFlag;
		}
		
		else 
		{
			this.m_manager.m_runningList[this.m_manager.m_runningLength++] = this;
			m_flags |= t_runningFlag;
		}
		
		m_goalTime = this.m_manager.m_systemTime + m_delay;
	}
	
	
	/**
	 * 暂停
	 */
	final public function pause() : void
	{
		if (m_flags & t_gcFlag)
		{
			Logger.reportError(this, 'start', '定时器已回收.');
		}
		
		if (!Boolean(m_flags & 0x0F))
		{
			return;
		}
		
		m_manager.stopTimer(this);
		
		m_flags &= t_gcAutoFlag;
	}
	

	/**
	 * 重置
	 * @param	autoStart
	 */
	final public function reset( autoStart:Boolean = false ) : void
	{
		m_currentCount = 0;
		
		if (autoStart)
		{
			this.start();
		}
		else
		{
			this.pause();
		}
	}
	
	
	/**
	 * 开关
	 */
	final public function toggle() : void
	{
		if (Boolean(m_flags & 0x0F))
		{
			this.pause();
		}
		else
		{
			this.start();
		}
	}
	
	
	final public function dispose() : void
	{
		if ( m_flags & t_gcFlag )
		{
			return;
		}
		
		this.removeAllRoundListeners();
		this.removeAllCompleteListeners();
		
		delete this.m_manager.m_timerMap[ m_timerName ];
		this.pause();
		
		m_flags    =  t_gcFlag;
		m_manager  =  null;
		
		//Logger.reportMessage(this, 'recycle timer (' + m_timerName + ') ... ( × ' + --this.m_manager.m_numTimer + ' )');
	}
	
	
	/**
	 * 加入延迟侦听
	 * @param	listener
	 * @param	priority
	 */
	final public function addRoundListener( listener:Function, priority:int = 0 ) : ITimer
	{
		(m_roundListener ||= ListenerProp.getListenerProp()).addListener(listener, priority);
		return this;
	}
	
	
	/**
	 * 移除延迟侦听
	 * @param	listener
	 */
	final public function removeRoundListener( listener:Function ) : void
	{
		if (!m_roundListener.removeListener(listener))
		{
			m_roundListener = null;
		}
	}
	
	
	/**
	 * 移除全部延迟侦听
	 */
	final public function removeAllRoundListeners() : void
	{
		if (m_roundListener)
		{
			m_roundListener.recycle();
			m_roundListener = null;
		}
	}
	
	
	
	/**
	 * 加入结束侦听
	 * @param	listener
	 * @param	priority
	 */
	final public function addCompleteListener( listener:Function, priority:int = 0 ) : ITimer
	{
		(m_completeListener ||= ListenerProp.getListenerProp()).addListener(listener, priority);
		return this;
	}
	
	
	/**
	 * 移除结束侦听
	 * @param	listener
	 */
	final public function removeCompleteListener( listener:Function ) : void
	{
		if (!m_completeListener.removeListener(listener))
		{
			m_completeListener = null;
		}
	}
	
	
	/**
	 * 移除全部结束侦听
	 */
	final public function removeAllCompleteListeners() : void
	{
		if (m_completeListener)
		{
			m_completeListener.recycle();
			m_completeListener = null;
		}
	}
	
	
	
	
	
	//======================
	// Internal
	//======================
	
	
	/**
	 * 初期化
	 * @param	delay
	 * @param	repeatCount
	 * @param	autoRecycle
	 * @param	timerName
	 */
	final internal function initialize( delay:Number, repeatCount:int, autoRecycle:Boolean, timerName:String ) : void
	{
		// 最小延迟间隔
		if ( delay < 0.03 )
		{
			Logger.reportError(this, 'addTimer', '延迟间隔不可低于0.03sec !!');
		}
		
		m_delay         =  delay * 1000.0;
		m_repeatCount   =  repeatCount;
		m_timerName     =  timerName;
		m_currentCount  =  0;
		m_flags         =  autoRecycle ? t_gcAutoFlag : 0;
	}
	
	
	/**
	 * 推进
	 * @param	deltaTime
	 * @return  true，停止
	 */
	final internal function advance() : Boolean
	{
		// 已停止
		if (!Boolean(m_flags & t_runningFlag))
		{
			return true
		}
		
		// 延迟侦听
		if (m_roundListener)
		{
			m_roundListener.execute();
		}
		
		// 结束
		if (m_repeatCount > 0 && ++m_currentCount >= m_repeatCount)
		{
			// 结束侦听
			if(m_completeListener)
			{
				m_completeListener.execute();
			}
			
			// 自动回收
			if (m_flags & t_gcAutoFlag)
			{
				this.dispose();
			}
			
			// 返回起点，停止
			else
			{
				this.reset(false);
			}
		
			return true;
		}
		
		var tmpT:Number = this.m_manager.m_systemTime - m_goalTime;
		m_goalTime += (m_delay - tmpT % m_delay);	
		
		return false;
	}
	
	
	
	
	private static var m_count:int;

	
	internal var m_manager:TimerManagerBase;
	
	internal var m_goalTime:Number;
	
	internal var m_flags:int;
	
	internal var timerId:uint;
	
	internal var m_timerName:String;

	internal var m_delay:Number;
	
	internal var m_currentCount:int;
	
	internal var m_repeatCount:int;

	
	//internal var m_startListenerProp:ListenerProp;
	
	internal var m_roundListener:ListenerProp;
	
	internal var m_completeListener:ListenerProp;
	
	
	
}

}